/* SexpMethodResponseMessage.cs -- 
   Copyright (C) 2008  Casey Marshall.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


using System;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;

namespace SexpSharp.Remoting
{
	class SexpMethodResponseMessage : IMethodReturnMessage
	{
		private object returnValue;
		private Exception exception;
		private object[] outArgs;
		private Type[] signature;
		private MethodBase methodBase;
		private string typename;
		private object[] args;
		private LogicalCallContext lcc;
		private string uri;
		private bool hasVarArgs;
		private string methodName;

		public SexpMethodResponseMessage(SexpResponse response,
										 IMethodCallMessage call)
		{
			returnValue = response.returnValue;
			signature = (Type[]) call.MethodSignature;
			methodBase = call.MethodBase;
			outArgs = response.outArgs;
			typename = call.TypeName;
            ParameterInfo[] param = methodBase.GetParameters();
            args = new object[param.Length];
            int i = 0, j = 0;
            foreach (ParameterInfo p in param)
            {
                if (p.IsOut || p.ParameterType.IsByRef)
                    args[i] = outArgs[j++];
                i++;
            }
			lcc = call.LogicalCallContext;
			uri = call.Uri;
			hasVarArgs = call.HasVarArgs;
			methodName = call.MethodName;
		}

		public SexpMethodResponseMessage(SexpFault fault,
										 IMethodCallMessage call)
		{
			exception = new RemotingException(fault.faultString);
			outArgs = new object[0];
		}

#region IMethodReturnMessage implementation

		public object GetOutArg(int arg_num)
		{
            System.Console.Error.WriteLine("GetOutArg " + arg_num);
			return outArgs[arg_num];
		}

        public string GetOutArgName(int arg_num)
		{
            System.Console.Error.WriteLine("GetOutArgName " + arg_num);
            ParameterInfo[] param = methodBase.GetParameters();
            foreach (ParameterInfo p in param)
                if (p.IsOut || p.ParameterType.IsByRef)
                    if (arg_num-- == 0)
                        return p.Name;
            throw new ArgumentException("no such outarg");
		}

        public Exception Exception {
			get {
				return exception;
			}
        }

        public int OutArgCount {
			get {
                System.Console.Error.WriteLine("OutArgCount is " + outArgs.Length);
				return outArgs.Length;
			}
        }

        public object[] OutArgs {
			get {
                System.Console.Error.WriteLine("OutArgs is " + outArgs);
				return outArgs;
			}
        }

        public object ReturnValue {
			get {
				return returnValue;
			}
        }

#endregion

#region IMethodMessage implementation

        public object GetArg(int arg_num)
		{
			return args[arg_num];
		}

        public string GetArgName (int arg_num) {
			return methodBase.GetParameters()[arg_num].Name;
		}

        public int ArgCount {
			get {
				if (args == null)
					return 0;
				return args.Length;
			}
        }

        public object[] Args {
			get {
				return args;
			}
        }

        public bool HasVarArgs {
			get {
				return hasVarArgs;
			}
        }

		public LogicalCallContext LogicalCallContext {
			get {
				return lcc;
			}
        }

        public MethodBase MethodBase {
			get {
				return methodBase;
			}
        }

        public string MethodName {
			get {
				return methodName;
			}
        }
        public object MethodSignature {
			get {
				return signature;
			}
        }

        public string TypeName {
			get {
				return typename;
			}
        }

        public string Uri {
			get {
				return uri;
			}
        }

#endregion

#region IMessage implementation

        public System.Collections.IDictionary Properties {
			get {
				return null;
			}
        }

#endregion
	}
}